package com.pangu;

import com.pangu.bean.ContextConfig;
import com.pangu.bean.DeviceConfig;
import com.pangu.bean.ModuleConfig;
import com.pangu.store.SharedPrefManager;
import com.pangu.task.IResultReceiver;
import com.pangu.util.DeviceUtil;
import com.pangu.util.MConstants;
import com.pangu.util.MobUtil;
import com.pangu.util.network.NetworkInfoParser;

import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.provider.Settings;
import android.support.multidex.MultiDex;
import android.support.multidex.MultiDexApplication;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import android.webkit.WebView;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * Application的基类
 * Created by cxlin on 2015/7/15.
 */
public abstract class AMApplication<B extends MobBeanManager, C extends SharedPrefManager, F extends ContextConfig>
        extends MultiDexApplication implements IResultReceiver,
        IAMHandlerRegister {

    public static final String TAG = AMApplication.class.getSimpleName();

    private static AMApplication mApplication;

    // 是否主进程(定义:进程名是包名，为主进程。其他的，比如service另起的进程，为子进程)
    private boolean isMainProcess;
    // 上一次更新时间
    protected volatile long lastInitTimestamp;
    // 基础数据是否初始化正常，如果基础数据不正常，那么不应该启动。
    private boolean baseDataOk = false;
    // Mob模块的Bean对象管理器
    protected B mBeanManager;
    // 当前使用的 window 环境，用于一些全局处理。
    private Context mWindowToken;
    // 全局处理器, 由receiver获得引用
    private MobBaseHandler mHandler;

    // ts时间戳（以1-10间的一个随机数代替）
    private String ts;

    /**
     * 获得实例，用于那些无法直接获取全局环境的地方。
     *
     * @return
     */
    public static AMApplication getInstance() {
        return mApplication;
    }

    @Override
    public void onCreate() {
        super.onCreate();
		
		try {
            // 是否是主进程,不是主进程，就跳过初始化，比如service的独立进程
            String processName = getCurProcessName();
            isMainProcess = getPackageName().equals(processName);
            if (!isMainProcess) {
                onRemoteProcessInit(processName);
                return;
            }

            mApplication = this;

            ts = String.valueOf(new Random().nextInt(9));
            lastInitTimestamp = System.currentTimeMillis();

            // 预初始化
            preInitApplication();
            // 实际初始化
            initMApplication();
            // 数据预加载
            initPreDataLoad();

            baseDataOk = true;

        } catch (Exception e) {
            e.printStackTrace();
            baseDataOk = false;
        }
    }

    /**
     * 获取与环境相关的根目录名
     *
     * @return
     */
    public String getContextRootPathName() {
        return getContextConfig().getRootPathName();
    }

    /**
     * 获得进程名
     *
     * @return
     */
    private String getCurProcessName() {
        String processName = null;
        try {
            int pid = android.os.Process.myPid();
            ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

            List<ActivityManager.RunningAppProcessInfo> appProcessList = mActivityManager.getRunningAppProcesses();
            if (appProcessList != null) {
                for (ActivityManager.RunningAppProcessInfo appProcess : appProcessList) {
                    if (appProcess.pid == pid) {
                        processName = appProcess.processName;
                        break;
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        // 正常这个不会发生的，如果一旦发生因为主线程最先初始化
        // isMainProcess为false，设置进程为主线程名
        if (processName == null) {
            if (!isMainProcess) {
                processName = getPackageName();
            }
        }

        return processName;
    }

    /**
     * 预初始化，这里做些需要提前处理的东西
     */
    protected void preInitApplication() {

    }

    /**
     * 初始化系统需要的数据
     *
     * @throws Exception
     */
    protected void initMApplication() throws Exception {
        // 处理器
        mHandler = new MobBaseHandler(getMainLooper());

        // Mob模块的Bean管理器初始化，要在所有实例前进行
        mBeanManager = createBeanManager();
        // 初始化基础数据
        // initDeviceConfig();
        initAndroidIdImeiConfig();
        // 检查本机网络，注意网络连通不是必须的。
        checkLocalNetwork();
        // 初始化配置
        initContextConfig();

        // 注册定时器处理
        initAlarmManager();

        // 扩展模块管理
        initSubModules();

    }

    /**
     * 由于初始化基础数据被废弃，我这边也没有全部开启 initDeviceConfig 这个函数
     * 暂时先写一个新的函数，仅用于获取 androidId 和 imei imsi
     *
     */
    protected void initAndroidIdImeiConfig() {
        DeviceConfig deviceConfig = getDeviceConfig();
        // 设备id
        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        String androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
        deviceConfig.setAndroidId(androidId);

        // imsi
        String imsi = tm.getSubscriberId();
        deviceConfig.setSimId(imsi);

        // imei  在三星平板机型上为空
        String imei = tm.getDeviceId();
        if(imei==null) {
            // android pad
            imei = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
        }
        deviceConfig.setImei(imei);
    }

    protected void initDeviceConfig() throws Exception {
        DeviceConfig deviceConfig = getDeviceConfig();
        SharedPrefManager sharedPrefManager = getSharedPrefManager();
        // 设备id
        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        String androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
        deviceConfig.setAndroidId(androidId);

        // imsi
        String imsi = tm.getSubscriberId();
        deviceConfig.setSimId(imsi);

        // imei
        String imei = tm.getDeviceId();
        deviceConfig.setImei(imei);

        // mac
        String mac = null;
        try {
            WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
            WifiInfo info = wifi.getConnectionInfo();
            mac = info.getMacAddress();
            deviceConfig.setMac(mac);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 手机型号名字(Nexus One)
        String model = Build.MODEL;
        deviceConfig.setModel(model);

        // 客户端的版本
        PackageManager manager = getPackageManager();
        PackageInfo info = manager.getPackageInfo(getPackageName(), 0);
        if (info != null) {
            deviceConfig.setVersion(info.versionName);
            deviceConfig.setVersionCode(info.versionCode);
        } else {
            deviceConfig.setVersion("1.0");
            deviceConfig.setVersionCode(1);
        }

        // 设置DES算法的秘钥
        StringBuffer desKey = new StringBuffer();
        for (int num : MConstants.COMMON_DES_KEY) {
            desKey.append((char) num);
        }
        deviceConfig.setDesKey(desKey.toString());

        // 是否模拟器
        try {
            deviceConfig.setEmulator(DeviceUtil.isEmulator(this));
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 固件版本
        String firmware = Build.VERSION.RELEASE;
        deviceConfig.setFirmware(firmware);

        // sdkversion
        int sdkVersion = Build.VERSION.SDK_INT;
        deviceConfig.setSdkVersion(sdkVersion);

        // 硬件架构
        deviceConfig.setAbi(DeviceUtil.getCpuAbi());

        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        Display display = windowManager.getDefaultDisplay();
        display.getMetrics(displayMetrics);

        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        deviceConfig.setResolution(width + "x" + height);

        int density = DeviceUtil.getDensityDpi(displayMetrics);
        deviceConfig.setDensity(String.valueOf(density));

        // 生成用户唯一标识uuid
        String uuid = sharedPrefManager.getUserUuid();
        uuid = DeviceUtil.createUuid(this, imei, mac);
        sharedPrefManager.saveUserUuid(uuid);
        deviceConfig.setUserUuid(uuid);

    }

    /**
     * 检查本地网络
     */
    public void checkLocalNetwork() {
        try {
            NetworkInfoParser.parserNetwork(null, this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 注册定时器处理
     *
     * @return
     */
    protected AlarmManager initAlarmManager() {
        // 注册定时更新
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent();
        intent.setPackage(getPackageName());
        PendingIntent contentIntent = null;

        // 最优IP适配，候选地址查询
        intent = new Intent();
        intent.setPackage(getPackageName());
        intent.setAction(MConstants.ACTION_UPDATE_CANDIDATE_ADDRESS_INFO);
        contentIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),
                MConstants.TIME_INTERVAL_UPDATE_CANDIDATE_ADDRESS_INFO, contentIntent);

        return alarmManager;
    }

    /**
     * 初始化模块
     */
    private void initSubModules() throws Exception {
        PreConfigManager preConfigManager = getPreConfigManager();
        ArrayList<ModuleConfig> moduleConfigList = preConfigManager.getModuleConfigList();
        if (moduleConfigList != null && moduleConfigList.size() > 0) {
            for (ModuleConfig moduleConfig : moduleConfigList) {
                getModuleManager().registerModule(moduleConfig.getModuleName(), moduleConfig);
            }
        }
    }

    /**
     * 执行必要的数据的预加载
     */
    protected void initPreDataLoad() {

    }

    @Override
    public final void onLowMemory() {
        super.onLowMemory();

        // 非主进程，不执行
        if (!isMainProcess) {
            return;
        }

        // 当在前台，不执行回收
        if (!MobUtil.isClientProcessInFront(this)) {
            // 垃圾回收
            handleMobEmptyMessage(MConstants.M_MOB_ACTION_RELEASE_MEMARY);
        }

        doOnLowMemory();
    }

    /**
     * 提供给子类覆盖onLowMemory()方法
     */
    protected void doOnLowMemory() {

    }

    @Override
    public final void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // 非主进程，不执行
        if (!isMainProcess) {
            return;
        }

        doOnConfigurationChanged();
    }

    /**
     * 提供给子类覆盖onConfigurationChanged()方法
     */
    protected void doOnConfigurationChanged() {

    }

    public boolean isBaseDataOk() {
        return baseDataOk;
    }

    public AModule getSubModule(String moduleMark) {
        return getModuleManager().getModule(moduleMark);
    }

    /**
     * 处理消息（同步方式）
     *
     * @param msg
     */
    public void handleMobMessageSync(Message msg) {
        if (mHandler != null) {
            mHandler.handleMessage(msg);
        }
    }

    /**
     * 处理消息
     *
     * @param msg
     */
    public void handleMobMessage(Message msg) {
        if (mHandler != null) {
            mHandler.sendMessage(msg);
        }
    }

    /**
     * 处理消息
     *
     * @param what
     */
    public void handleMobEmptyMessage(int what) {
        if (mHandler != null) {
            mHandler.sendEmptyMessage(what);
        }
    }

    /**
     * 延时处理消息
     *
     * @param msg
     * @param delayMillis
     */
    public void handleMobDelayMessage(Message msg, long delayMillis) {
        if (mHandler != null) {
            mHandler.sendMessageDelayed(msg, delayMillis);
        }
    }

    /**
     * 延时处理消息
     *
     * @param what
     * @param delayMillis
     */
    public void handleMobEmptyDelayMessage(int what, long delayMillis) {
        if (mHandler != null) {
            mHandler.sendEmptyMessageDelayed(what, delayMillis);
        }
    }

    /**
     * 主消息处理器
     * arg1: 状态消息，如果被标示为Constants.MESSAGE_END，则表明这个消息不需要再由后续处理。
     * arg2: 用户自定义数据放这里，不能放大arg1里
     */
    private class MobBaseHandler extends Handler {
        // 消息处理顺序 : application -> module(最先注册的模块最先收到消息) -> ui(最后注册的ui最先收到消息)
        private List<AMHandler> handlerList = new ArrayList<AMHandler>();

        public MobBaseHandler(Looper looper) {
            super(looper);
        }

        synchronized void registeHandler(AMHandler handler) {
            // 如果是模块，则要插入到前排模块的队尾，UI模块的队头
            int index = 0;
            for (; index < handlerList.size(); index++) {
                if (!(handlerList.get(index) instanceof AModule)) {
                    break;
                }
            }
            handlerList.add(index, handler);
        }

        synchronized void unregistHandler(AMHandler handler) {
            handlerList.remove(handler);
        }

        @Override
        public void handleMessage(Message msg) {
            try {
                // application（包括父类和子类application）先处理消息
                switch (msg.what) {
                    case MConstants.M_MOB_ACTION_RELEASE_MEMARY:
                        releaseForExist(msg);
                        break;

                    case MConstants.M_MOB_STATUS_NETWORKINFO_CHANGE:
                        // 先解析网络
                        parseNetworkInfo(msg);

                        break;

                    default:
                        subHandleMessage(msg);
                        break;
                }

                // 传递给注册的模块和UI
                // 消息是否终止
                if (msg.arg1 != MConstants.M_MESSAGE_END) {
                    for (AMHandler handler : handlerList) {
                        handler.handleMessage(msg); // 注意这里是同步进行，不使用sendMessage();
                    }
                }

                // Application及子模块和注册的处理器完成后，交由子Application来处理业务消息
                if (msg.arg1 != MConstants.M_MESSAGE_END) {
                    handleBussnessMessage(msg);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 延时gc，资源释放
     *
     * @param msg
     */
    protected void releaseForExist(Message msg) {
        msg.arg1 = MConstants.M_MESSAGE_END;

        // 清除内存缓存（自己构建的）
        try {

        } catch (Exception e) {
        }
    }

    /**
     * 解析处理网络信息
     *
     * @param msg
     */
    private void parseNetworkInfo(Message msg) {
        NetworkInfo networkInfo = (NetworkInfo) msg.obj;
        NetworkInfoParser.parserNetwork(networkInfo, this);
    }

    /**
     * 清除所有WebView缓存
     */
    private void clearWebViewCache() {
        WebView webView = new WebView(this);
        webView.clearCache(true);
    }

    /**
     * 长时间存活是初始化相关数据
     *
     * @param force 是否强制
     */
    public boolean checkForLongLive(boolean force) {
        long currentTimestamp = System.currentTimeMillis();

        if (force || currentTimestamp - lastInitTimestamp >= MConstants.maxContextReinit) {
            lastInitTimestamp = currentTimestamp;

            // 初始其他模块
            Map<String, AModule> moduleViewMap = getModuleManager().getModuleMapView();
            for (Map.Entry<String, AModule> entry : moduleViewMap.entrySet()) {
                try {
                    entry.getValue().initForLongLive();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            return true;

        } else {
            return false;
        }
    }

    public Context getMWindowToken() {
        return mWindowToken;
    }

    public void setMWindowToken(Context mWindowToken) {
        this.mWindowToken = mWindowToken;
    }

    @Override
    public void registerSubHandler(AMHandler handler) {
        mHandler.registeHandler(handler);
    }

    /**
     * 务必相关部分在退出的时候取消自己的注册
     */
    @Override
    public void unregisterSubHandler(AMHandler handler) {
        mHandler.unregistHandler(handler);
    }

    public String getTs() {
        return ts;
    }

    public B getBeanManager() {
        return mBeanManager;
    }

    public DeviceConfig getDeviceConfig() {
        return mBeanManager.getDeviceConfig();
    }

    public ModuleManager getModuleManager() {
        return mBeanManager.getModuleManager();
    }

    public PreConfigManager getPreConfigManager() {
        return mBeanManager.getPreConfigManager();
    }

    protected abstract B createBeanManager();

    public abstract C getSharedPrefManager();

    public abstract F getContextConfig();

    /**
     * 远程进程的初始化
     */
    protected abstract void onRemoteProcessInit(String processName) throws Exception;

    /**
     * 初始化运行时的上下文配置
     */
    protected abstract void initContextConfig() throws Exception;

    /**
     * 获得模块配置文件名，一定要放在assets目录下
     *
     * @return
     */
    public abstract String getModulesConfigName();

    /**
     * 获得平台标识（手机，pad，tv等）
     *
     * @return
     */
    public abstract int getClientMark();

    /**
     * 获得客户端类型
     *
     * @return 客户端类型 0：普通    Ota类型 1： A类型 2：B类型
     */
    public abstract int getClientType();

    /**
     * 子类Application处理的信息， 这个方法在子模块和注册的handler处理前执行
     */
    protected abstract void subHandleMessage(Message msg);

    /**
     * 子类Application处理最终的业务信息， 这个方法对消息的处理将在所有子模块和注册的handler之后
     * 主要用于在各Application、各模块以及各注册的处理器处理完成之后，处理最终的业务消息，比如发送通知，UI刷新等
     */
    protected abstract void handleBussnessMessage(Message msg);

}
